package com.game.doudizhu.core;

import com.game.doudizhu.common.exception.GameException;
import com.game.doudizhu.model.*;
import com.game.doudizhu.common.constants.GameConstants;
import com.game.doudizhu.util.CardPatternUtil;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class DoudizhuGameLogic {
    
    // === 游戏初始化和状态转换 ===
    public GameState initializeGame(GameRoom room) {
        GameState gameState = new GameState(room);
        gameState.setBidding(true);
        gameState.setPlaying(false);
        
        // 随机选择第一个叫分的玩家
        List<Player> players = new ArrayList<>(room.getPlayers());
        Collections.shuffle(players);
        gameState.setCurrentBidder(players.get(0).getId());
        
        return gameState;
    }

    public void startPlaying(GameState gameState) {
        validateLandlord(gameState);
        
        gameState.setBidding(false);
        gameState.setPlaying(true);
        gameState.setCurrentPlayerId(gameState.getLandlordId());
        gameState.setLandlordRevealed(true);
        gameState.setMultiple(gameState.getMaxBid());
        
        distributeLandlordCards(gameState);
    }

    // === 游戏核心逻辑 ===
    public void handleBidding(GameState gameState, BidMessage bidMessage) {
        validateBidding(gameState, bidMessage);
        updateBidState(gameState, bidMessage);
        
        // 如果有人叫3分，直接结束叫分阶段
        if (bidMessage.getBidPoints() == 3) {
            gameState.setBidding(false);
            return;
        }
        
        // 如果所有人都叫过分了
        if (gameState.isAllPlayersBid()) {
            // 检查是否所有人都叫了0分
            boolean allZeroBids = gameState.getPlayerBids().values().stream()
                    .allMatch(bid -> bid == 0);
            
            if (allZeroBids) {
                // 标记需要重新发牌
                gameState.setNeedRestart(true);
            }
            
            gameState.setBidding(false);
            return;
        }
        
        // 否则移动到下一个叫分玩家
        moveToNextBidder(gameState);
    }

    public void handlePlayCards(GameState gameState, PlayCardMessage playCardMessage, List<Card> cardsToPlay) {
        validatePlayTurn(gameState, playCardMessage);
        validatePlayCards(cardsToPlay, gameState.getLastPlayedCards());
        processPlayCards(gameState, playCardMessage, cardsToPlay);
    }

    public void handlePass(GameState gameState, Player player) {
        validatePassTurn(gameState, player);
        moveToNextPlayer(gameState);
    }

    // === 游戏状态检查 ===
    public boolean isGameOver(GameState gameState) {
        return hasPlayerFinished(gameState) || hasPlayerDisconnected(gameState);
    }

    public boolean canStartGame(GameState gameState) {
        return gameState.getMaxBid() == 3 || (gameState.getMaxBid() > 0 && isAllPlayersBid(gameState));
    }

    // === 分数计算 ===
    public void calculateFinalScores(GameState gameState) {
        int totalScore = calculateTotalScore(gameState);
        distributeScores(gameState, totalScore);
    }

    // ... 其他验证和辅助方法 ...

    // === 验证方法 ===
    private void validateLandlord(GameState gameState) {
        if (gameState.getLandlordId() == null) {
            throw new GameException("还未确定地主");
        }
    }

    private void validateBidding(GameState gameState, BidMessage bidMessage) {
        if (!gameState.isBidding()) {
            throw new GameException("不在叫分阶段");
        }
        if (!bidMessage.getPlayerId().equals(gameState.getCurrentBidder())) {
            throw new GameException("还没轮到你叫分");
        }
        if (bidMessage.getBidPoints() < 0 || bidMessage.getBidPoints() > 3) {
            throw new GameException("叫分必须在0-3之间");
        }
        if (bidMessage.getBidPoints() != 0 && bidMessage.getBidPoints() <= gameState.getMaxBid()) {
            throw new GameException("必须叫比当前最高分更高的分数");
        }
    }

    private void validatePlayTurn(GameState gameState, PlayCardMessage playCardMessage) {
        if (!playCardMessage.getPlayerId().equals(gameState.getCurrentPlayerId())) {
            throw new GameException("还没轮到你出牌");
        }
    }

    private void validatePassTurn(GameState gameState, Player player) {
        if (!player.getId().equals(gameState.getCurrentPlayerId())) {
            throw new GameException("还没轮到你的回合");
        }
    }

    private void validatePlayCards(List<Card> cardsToPlay, List<Card> lastPlayedCards) {
        CardPatternUtil.CardPattern currentPattern = CardPatternUtil.getPattern(cardsToPlay);
        if (currentPattern == CardPatternUtil.CardPattern.INVALID) {
            throw new GameException("出牌不合法：无效的牌型");
        }

        if (lastPlayedCards == null || lastPlayedCards.isEmpty()) {
            return;
        }

        validateAgainstLastPlay(cardsToPlay, lastPlayedCards, currentPattern);
    }

    // === 游戏状态更新方法 ===
    private void updateBidState(GameState gameState, BidMessage bidMessage) {
        if (bidMessage.getBidPoints() > gameState.getMaxBid()) {
            gameState.setMaxBid(bidMessage.getBidPoints());
            gameState.setLandlordId(bidMessage.getPlayerId());
        }
        gameState.getPlayerBids().put(bidMessage.getPlayerId(), bidMessage.getBidPoints());
    }

    private void moveToNextBidder(GameState gameState) {
        Set<Player> players = gameState.getRoom().getPlayers();
        List<Long> playerIds = players.stream()
                .map(Player::getId)
                .collect(Collectors.toList());
                
        int currentIndex = playerIds.indexOf(gameState.getCurrentBidder());
        int nextIndex = (currentIndex + 1) % playerIds.size();
        
        gameState.setCurrentBidder(playerIds.get(nextIndex));
    }

    public void moveToNextPlayer(GameState gameState) {
        List<Long> playerIds = new ArrayList<>(gameState.getPlayerCards().keySet());
        int currentIndex = playerIds.indexOf(gameState.getCurrentPlayerId());
        Long nextPlayerId = playerIds.get((currentIndex + 1) % playerIds.size());
        
        // 如果下一个玩家是上一轮出牌的玩家，说明一轮结束，清除上一轮出牌记录
        if (nextPlayerId.equals(gameState.getLastPlayerId())) {
            gameState.setLastPlayedCards(null);
            gameState.setLastPlayerId(null);
        }
        
        gameState.setCurrentPlayerId(nextPlayerId);
    }

    // === 牌型验证和处理方法 ===
    private void validateAgainstLastPlay(List<Card> cardsToPlay, List<Card> lastPlayedCards, 
                                       CardPatternUtil.CardPattern currentPattern) {
        CardPatternUtil.CardPattern lastPattern = CardPatternUtil.getPattern(lastPlayedCards);
        if(currentPattern == CardPatternUtil.CardPattern.ROCKET) return;
        if(lastPattern == CardPatternUtil.CardPattern.ROCKET) {
            throw new GameException("火箭是最大的牌，无法压过");
        }

        if (currentPattern == CardPatternUtil.CardPattern.BOMB
            && lastPattern != CardPatternUtil.CardPattern.BOMB) {
            return;
        }

        if (currentPattern != lastPattern || cardsToPlay.size() != lastPlayedCards.size()) {
            throw new GameException("出牌不合法：牌型不匹配");
        }

        if (!CardPatternUtil.isGreaterThan(cardsToPlay, lastPlayedCards)) {
            throw new GameException("出牌不合法：牌值太小");
        }
    }

    public List<Card> getCardsToPlay(GameState gameState, PlayCardMessage playCardMessage) {
        List<Card> playerCards = gameState.getPlayerCards().get(playCardMessage.getPlayerId());
        if (playerCards == null) {
            throw new GameException("玩家手牌不存在");
        }

        // 创建一个Map来存储玩家手牌，以cardId为key
        Map<Long, Card> playerCardMap = new HashMap<>();
        for (Card card : playerCards) {
            playerCardMap.put(card.getId(), card);
        }

        // 检查每个要出的牌是否在玩家手牌中
        List<Card> cardsToPlay = new ArrayList<>();
        for (Long cardId : playCardMessage.getCardIds()) {
            Card card = playerCardMap.get(cardId);
            if (card == null) {
                throw new GameException("出牌不合法：部分牌不在你的手牌中");
            }
            cardsToPlay.add(card);
        }

        // 验证数量是否匹配
        if (cardsToPlay.size() != playCardMessage.getCardIds().size()) {
            throw new GameException("出牌不合法：部分牌不在你的手牌中");
        }

        return cardsToPlay;
    }

    private void processPlayCards(GameState gameState, PlayCardMessage playCardMessage, List<Card> cardsToPlay) {
        List<Card> playerCards = gameState.getPlayerCards().get(playCardMessage.getPlayerId());
        playerCards.removeAll(cardsToPlay);
        
        gameState.setLastPlayedCards(cardsToPlay);
        gameState.setLastPlayerId(playCardMessage.getPlayerId());
        
        if (playerCards.isEmpty()) {
            gameState.setWinner(playCardMessage.getPlayerId());
            return;
        }
        
        CardPatternUtil.CardPattern pattern = CardPatternUtil.getPattern(cardsToPlay);
        if (pattern == CardPatternUtil.CardPattern.BOMB || 
            pattern == CardPatternUtil.CardPattern.ROCKET) {
            gameState.incrementBombCount();
        }
        
        moveToNextPlayer(gameState);
    }

    // === 游戏结束相关方法 ===
    private boolean hasPlayerFinished(GameState gameState) {
        return gameState.getPlayerCards().values().stream().anyMatch(List::isEmpty);
    }

    private boolean hasPlayerDisconnected(GameState gameState) {
        return gameState.getRoom().getPlayers().size() < 3;
    }

    private boolean isAllPlayersBid(GameState gameState) {
        return gameState.isAllPlayersBid();
    }

    private int calculateTotalScore(GameState gameState) {
        return gameState.getMaxBid() * (int)Math.pow(2, gameState.getBombCount());
    }

    private void distributeScores(GameState gameState, int totalScore) {
        Long landlordId = gameState.getLandlordId();
        boolean isLandlordWin = gameState.getWinner().equals(landlordId);

        for (Map.Entry<Long, List<Card>> entry : gameState.getPlayerCards().entrySet()) {
            Long playerId = entry.getKey();
            boolean isLandlord = playerId.equals(landlordId);
            
            int score;
            if (isLandlord) {
                score = isLandlordWin ? totalScore * 2 : -totalScore * 2;
            } else {
                score = isLandlordWin ? -totalScore : totalScore;
            }
            
            gameState.getPlayerScores().put(playerId, score);
        }
    }

    private void distributeLandlordCards(GameState gameState) {
        Long landlordId = gameState.getLandlordId();
        List<Card> landlordCards = gameState.getLandlordCards();
        
        if (landlordCards == null || landlordCards.isEmpty()) {
            throw new GameException("地主牌不存在");
        }
        
        List<Card> landlordHandCards = gameState.getPlayerCards().get(landlordId);
        landlordHandCards.addAll(landlordCards);
        
        gameState.getRoom().getPlayers().forEach(player -> {
            if (player.getId().equals(landlordId)) {
                player.setRole(GameConstants.Role.LANDLORD);
            } else {
                player.setRole(GameConstants.Role.FARMER);
            }
        });
    }
} 